#include <iostream>
#include "Dependancy.h"

void DepController::AddDep(
    const string &module,
    const vector<string> &deps)
{
    if (depmap.find(module) == depmap.end()) {
        depmap[module] = deps;
    }
}


void DepController::Install(
    const string &module,
    bool isexplicit)
{
    if (mlist.find(module) != mlist.end()) {
        if (isexplicit) {
            cout << "\t" << module << " is already installed" << endl;
        }
        return;
    }

    if (depmap.find(module) != depmap.end()) {
        // traverse dependency list
        vector<string> &deps = depmap[module];
        for (int i=0; i < (int)deps.size(); i++) {
            Install(deps[i], false);
            mlist[deps[i]].numdeps ++;
        }
    }
    mproperties_t mp(isexplicit, 0);
    mlist[module] = mp;
    cout << "\t" << "Installing " << module << endl;
}

void DepController::Remove(
    const string &module,
    bool isexplicit)
{
    if (mlist.find(module) == mlist.end()) {
        if (isexplicit) cout << "\t" << module << " is not installed" << endl;
        return;
    }

    // Do not remove a module if it is currently used,
    // or if it is explicitly installed and to be removed implicitly
    if (mlist[module].numdeps > 0 ||
        (!isexplicit && mlist[module].isexplicit))
    {
        if (isexplicit) cout << "\t" << module << " is still needed" << endl;
        return;
    }

    cout << "\t" << "Removing " << module << endl;
    mlist.erase(module);

    if (depmap.find(module) != depmap.end()) {
        // traverse dependency list
        vector<string> &deps = depmap[module];
        for (int i=0; i < (int)deps.size(); i++) {
            mlist[deps[i]].numdeps--;
            Remove(deps[i], false);
        }
    }
}

void DepController::ListAll()
{
    // list all modules
    for (unordered_map<string, mproperties_t>::iterator it = mlist.begin();
         it != mlist.end(); it++)
    {
        cout << "\t" << it->first << endl;
    }
}

void DepController::Exec(
    const string &cmd,
    const string &module,
    const vector<string> &params)
{
    if (cmd == "DEPEND") AddDep(module, params);
    else if (cmd == "INSTALL") Install(module, true);
    else if (cmd == "REMOVE") Remove(module, true);
    else if (cmd == "LIST") ListAll();
    else cout << "\t Unknown command " << cmd << endl;
}
